package org.example.weboj.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.Set;

public class ChatWebSocketHandler extends TextWebSocketHandler {

    private static final ObjectMapper objectMapper = new ObjectMapper(); // 用于解析 JSON 消息

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 不需要额外处理，等待消息到来
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 解析收到的消息
        String payload = message.getPayload();
        Message msg = objectMapper.readValue(payload, Message.class);  // 将 JSON 转换为 Message 对象

        // 判断消息类型并处理
        switch (msg.getType()) {
            case "create":
                handleCreateRoom(session, msg.getRoomId(), msg.getClientId());
                break;
            case "join":
                handleJoinRoom(session, msg.getRoomId(), msg.getClientId());
                break;
            case "chat":
                handleMessage(session, msg.getType(), "user", msg.getRoomId(), msg.getMessage());
                break;
            case "code":
                handleCode(session, msg.getType(), msg.getAction(), msg.getRoomId(), msg.getMessage(), msg.getCodeHash(), RoomManager.getRooms_master().get(msg.getRoomId()), msg.getCursor(), msg.getClientId());
                break;
            default:
                sendStructuredMessage(session, "chat", "error", "Invalid action. Please use 'create', 'join', or 'chat'.");
                break;
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String room = getRoomFromSession(session);
        if (room != null) {
            RoomManager.leaveRoom(room, session);  // 退出房间
            broadcastOnlineCount(room);
        }
    }

    private void sendStructuredMessage(WebSocketSession session, String type, String subtype, Object content) throws IOException {
        OutgoingMessage outMsg = new OutgoingMessage(type, subtype, content);
        String json = objectMapper.writeValueAsString(outMsg);
        session.sendMessage(new TextMessage(json));
    }

    private void sendStructuredCode(WebSocketSession session, String type, String subtype, Object content, String codeHash, String masterId, Message.Cursor cursor, String clientId) throws IOException {
        OutgoingMessage outMsg = new OutgoingMessage(type, subtype, content, codeHash, masterId, cursor, clientId);
        String json = objectMapper.writeValueAsString(outMsg);
        session.sendMessage(new TextMessage(json));
    }

    // 处理创建房间的逻辑
    private void handleCreateRoom(WebSocketSession session, String room, String clientId) throws Exception {
        if (RoomManager.roomExists(room)) {
            sendStructuredMessage(session, "chat", "error", "Room " + room + " already exists. Please choose a different room name.");
        } else {
            RoomManager.createRoom(room, session);  // 创建房间
            RoomManager.createRoomMaster(room, clientId);
            session.getAttributes().put("roomId", room);
            broadcastOnlineCount(room);
            sendStructuredMessage(session, "chat", "system", "Room " + room + " created successfully!");
        }
    }

    // 处理加入房间的逻辑
    private void handleJoinRoom(WebSocketSession session, String room, String clientId) throws Exception {
        if (RoomManager.roomExists(room)) {
            boolean success = RoomManager.joinRoom(room, session);  // 加入房间
            if (success) {
                session.getAttributes().put("roomId", room);
                broadcastOnlineCount(room);
                broadcastMessageToRoom(session, "chat", "system", room, clientId + " Joined room " + room + " successfully!");
            } else {
                sendStructuredMessage(session, "chat", "error", "Failed to join room " + room + ". Room is full or error occurred.");
            }
        } else {
            sendStructuredMessage(session, "chat", "error", "Room " + room + " does not exist!");
        }
    }

    // 处理聊天消息
    private void handleMessage(WebSocketSession session,String type,String subtype, String room, Object message) throws Exception {
        broadcastMessageToRoom(session, type, subtype, room, message);
    }

    private void handleCode(WebSocketSession session, String type, String subtype, String room, Object message, String codeHash, String masterId, Message.Cursor cursor, String clientId) throws Exception {
        broadcastCodeToRoom(session, type, subtype, room, message, codeHash, masterId, cursor, clientId);
    }

    // 从 WebSocket 会话中获取房间号
    private String getRoomFromSession(WebSocketSession session) {
        // 这里可以从 session 中的属性中获取房间信息，或者从消息中获取
        return session.getAttributes().get("roomId").toString(); // 假设在 session 中存储了房间信息
    }

    // 向房间内的所有用户广播消息
    private void broadcastMessageToRoom(WebSocketSession session, String type, String subtype, String room, Object message) throws Exception {
        Set<WebSocketSession> roomSessions = RoomManager.getRoomSessions(room);
        if (roomSessions != null) {
            for (WebSocketSession s : roomSessions) {
                if (!s.equals(session) && s.isOpen()) {
                    sendStructuredMessage(s, type, subtype, message);  // 向房间内的每个用户发送消息
                }
            }
        }
    }

    private void broadcastCodeToRoom(WebSocketSession session, String type, String subtype, String room, Object message, String codeHash, String masterId, Message.Cursor cursor, String clientId) throws Exception {
        Set<WebSocketSession> roomSessions = RoomManager.getRoomSessions(room);
        if (roomSessions != null) {
            for (WebSocketSession s : roomSessions) {
                if (!s.equals(session) && s.isOpen()) {
                    sendStructuredCode(s, type, subtype, message, codeHash, masterId, cursor, clientId);  // 向房间内的每个用户发送消息
                }
            }
        }
    }

    private void broadcastOnlineCount(String room) throws IOException {
        int count = RoomManager.getRoomSize(room);
        Set<WebSocketSession> sessions = RoomManager.getRoomSessions(room);

        if (sessions != null) {
            for (WebSocketSession sess : sessions) {
                sendStructuredMessage(sess, "chat", "onlineCount", count);
            }
        }
    }
}
